<?php

/**
 * Text helper class.
 *
 * @version  $Id: text.php 2 2009-10-02 23:06:43Z perfilev $
 * @package  Application
 */

class Text
{
	
	const CHANGES_SAVED    = 'Changes have been saved successfully.';
	const RECORD_ADDED     = 'New record has been added.';
	const VALIDATION_ERROR = 'Validation error has been detected.';

	// Validation custom errors (without ending '.')
	const DUPLICATE_KEY = 'Duplicate key';

	public static $states = array(
		'AL' => 'Alabama',
		'AK' => 'Alaska',
		'AS' => 'American Samoa',
		'AZ' => 'Arizona',
		'AR' => 'Arkansas',
		'CA' => 'California',
		'CO' => 'Colorado',
		'CT' => 'Connecticut',
		'DE' => 'Delaware',
		'DC' => 'District of Columbia',
		'FM' => 'Federated States of Micronesia',
		'FL' => 'Florida',
		'GA' => 'Georgia',
		'GU' => 'Guam',
		'HI' => 'Hawaii',
		'ID' => 'Idaho',
		'IL' => 'Illinois',
		'IN' => 'Indiana',
		'IA' => 'Iowa',
		'KS' => 'Kansas',
		'KY' => 'Kentucky',
		'LA' => 'Louisiana',
		'ME' => 'Maine',
		'MH' => 'Marshall Islands',
		'MD' => 'Maryland',
		'MA' => 'Massachusetts',
		'MI' => 'Michigan',
		'MN' => 'Minnesota',
		'MS' => 'Mississippi',
		'MO' => 'Missouri',
		'MT' => 'Montana',
		'NE' => 'Nebraska',
		'NV' => 'Nevada',
		'NH' => 'New Hampshire',
		'NJ' => 'New Jersey',
		'NM' => 'New Mexico',
		'NY' => 'New York',
		'NC' => 'North Carolina',
		'ND' => 'North Dakota',
		'MP' => 'Northern Mariana Islands',
		'OH' => 'Ohio',
		'OK' => 'Oklahoma',
		'OR' => 'Oregon',
		'PW' => 'Palau',
		'PA' => 'Pennsylvania',
		'PR' => 'Puerto Rico',
		'RI' => 'Rhode Island',
		'SC' => 'South Carolina',
		'SD' => 'South Dakota',
		'TN' => 'Tennessee',
		'TX' => 'Texas',
		'UT' => 'Utah',
		'VT' => 'Vermont',
		'VI' => 'Virgin Islands',
		'VA' => 'Virginia',
		'WA' => 'Washington',
		'WV' => 'West Virginia',
		'WI' => 'Wisconsin',
		'WY' => 'Wyoming',
	);

	public static $instances = array();

	public static $resources;

	public static $resource;

	public static function instance($name = 'default')
	{
		if (false == isset(self::$resources[$name])) {
			$file = APPLICATION_PATH . 'resources/'.$name.'.dat';
			if(is_file($file)) {
				self::$resources[$name] = self::initialize($file);
				
			} elseif($name != 'default') {
				$name = 'default';
				self::instance($name);
			} else {
				throw new Exception('Default resource not found.');
			}
		}

		return self::$resource = self::$resources[$name];
	}

	/**
	 * Static initialization.
	 *
	 * @return void
	 */
	public static function initialize($file)
	{
		function parseIniFile($path)
		{
			$res = $matches = array();
			$cat = &$res;
			$s = '\s*([[:alnum:]_\- \*]+?)\s*';
			preg_match_all('#^\s*((\[' . $s . '\])|(("?)' . $s . '\\5\s*=\s*("?)(.*?)\\7))\s*(;[^\n]*?)?$#ums', file_get_contents($path), $matches, PREG_SET_ORDER);
			foreach ($matches as $match) {
				if (empty($match[2])) {
					$cat[$match[6]] = $match[8];
				} else {
					$cat = &$res[$match[3]];
				}
			}
			return $res;
		}

		$data = parseIniFile($file, true);
		return $data;
	}

	/**
	 * Returns formated message with pluralization. Message could be passed
	 * directly or by the identifier of text resource.
	 *
	 * This method takes an arbitrary number of arguments to replace the tokens.
	 * Each token must be unique, and must increment in the format {0}, {1}, etc.
	 *
	 * If token contains word forms in the format {0|...|...} it will be pluralized.
	 *
	 * @param string $id Message or text resource identifier.
	 * @param ...
	 * @returns string
	 */
	public static function get($id)
	{
		$dot = strpos($id, '.');
		if (false !== $dot) {
			$cat = substr($id, 0, $dot);
			$key = substr($id, $dot + 1);
			if (
				   array_key_exists($cat, self::$resource)
				&& array_key_exists($key, self::$resource[$cat])
			) {
				$message = self::$resource[$cat][$key];
			} else {
				$message = $id;
			}
		} else {
			if (array_key_exists($id, self::$resource)) {
				$message = self::$resource[$id];
			} else {
				$message = $id;
			}
		}
		if (func_num_args() > 1) {
			$values = func_get_args();
			array_shift($values);
			
			return preg_replace_callback('/{(\d+)(\|.*?)?}/us', create_function(
				'$matches, $values',
				'
					$index = $matches[1];
					if (array_key_exists($index, $values)) {
						if (count($matches) == 3) {
							$forms = array_slice(explode('|', $matches[2]), 1);
							return Text::plural($values[$index], $forms);
						} else {
							return $values[$index];
						}
					} else {
						return $matches[0];
					}
				'), $message);
			
//			return preg_replace_callback('/{(\d+)(\|.*?)?}/us', function ($matches) use ($values) {
//					$index = $matches[1];
//					if (array_key_exists($index, $values)) {
//						if (count($matches) == 3) {
//							$forms = array_slice(explode('|', $matches[2]), 1);
//							return Text::plural($values[$index], $forms);
//						} else {
//							return $values[$index];
//						}
//					} else {
//						return $matches[0];
//					}
//				}, $message);
		} else {
			return $message;
		}
	}

	/**
	 * Pluralization for English language.
	 *
	 * Word forms is an array with two or three elements.
	 * The third element (if exists) will be used if the number is zero.
	 *
	 * Every occurrence of % in the word form will be replaced by the number.
	 * Note that \% becomes a literal % character.
	 *
	 * @param integer $n     The number.
	 * @param array   $forms Word forms.
	 * @return string
	 */
	public static function plural($n, array $forms)
	{
		$n = intval($n);
		if (3 == count($forms)) {
			$form = 0 == $n ? $forms[2] : $forms[1 == $n ? 0 : 1];
		} else {
			$form = $forms[1 == $n ? 0 : 1];
		}
		if (false !== mb_strpos($form, '%')) {
			return preg_replace(array('/(^|[^\\\\])%/u', '/\\\\%/u'), array('${1}' . $n, '%'), $form);
		} else {
			return $form;
		}
	}

	public static function mysqlDateTimeToPhp($data)
	{
		$res = '';
		$part = explode(' ', $data);
		$ymd = explode ('-', $part[0]);
		$hms = explode (':', $part[1]);
		$res .= $ymd[2];
		$res .= '.' . $ymd[1];
		$res .= '.' . $ymd[0];
		$res .= ' ' . $hms[0];
		$res .= ':' . $hms[1];
		$res .= ':' . $hms[2];
		return mktime($hms[0], $hms[1], $hms[2], $ymd[1], $ymd[2], $ymd[0]);
	}

	public static function mysqlDateToPhp($data)
	{
		$res = '';
		$ymd = explode ('-', $data);
		return mktime(0, 0, 0, $ymd[1], $ymd[2], $ymd[0]);
	}

	/**
	 * Replaces in tokens in the message.
	 *
	 * This method takes an arbitrary number of arguments to replace the tokens.
	 * Each token must be unique, and must increment in the format {0}, {1}, etc.
	 *
	 * @param string $message  Message.
	 * @return string
	 */
	public static function format($message)
	{
		$values = func_get_args();
		array_shift($values);
		if (0 < $c = count($values)) {
			$tokens = array();
			for ($i = 0; $i < $c; $i++) {
				$tokens[] = '{' . $i . '}';
			}
			return str_replace($tokens, $values, $message);
		} else {
			return $message;
		}
	}

}
